//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Xml;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Data;
using DotNetNuke.Entities.Host;
using DotNetNuke.Entities.Users;

namespace DotNetNuke.Services.FileSystem
{
	public class FileController
	{
        #region "Private Methods"
        private static void UpdateFileVersion(int fileId)
        {
            DataProvider.Instance().UpdateFileVersion(fileId, Guid.NewGuid());
        }
        #endregion


		internal bool FileChanged(DataRow drOriginalFile, string NewFileName, string NewExtension, long NewSize, int NewWidth, int NewHeight, string NewContentType, string NewFolder)
		{
			if (Convert.ToString(drOriginalFile["FileName"]) != NewFileName || Convert.ToString(drOriginalFile["Extension"]) != NewExtension || Convert.ToInt32(drOriginalFile["Size"]) != NewSize || Convert.ToInt32(drOriginalFile["Width"]) != NewWidth || Convert.ToInt32(drOriginalFile["Height"]) != NewHeight || Convert.ToString(drOriginalFile["ContentType"]) != NewContentType || Convert.ToString(drOriginalFile["Folder"]) != NewFolder)
			{
				return true;
			}
			return false;
		}
		public int AddFile(FileInfo file)
		{
		    int FileId = DataProvider.Instance().AddFile(file.PortalId, file.UniqueId, file.VersionGuid, file.FileName,
		                                                 file.Extension, file.Size, file.Width, file.Height, file.ContentType,
		                                                 file.Folder, file.FolderId,
		                                                 UserController.GetCurrentUserInfo().UserID, file.SHA1Hash);
			DataCache.RemoveCache("GetFileById" + FileId.ToString());
			return FileId;
		}
        public void UpdateFile(FileInfo file)
        {
            DataProvider.Instance().UpdateFile(file.FileId, file.VersionGuid, file.FileName, file.Extension, file.Size, file.Width, file.Height, file.ContentType, file.Folder, file.FolderId,
            UserController.GetCurrentUserInfo().UserID, file.SHA1Hash);
            DataCache.RemoveCache("GetFileById" + file.FileId.ToString());
        }

		public void ClearFileContent(int FileId)
		{
			DataProvider.Instance().UpdateFileContent(FileId, null);
		    UpdateFileVersion(FileId);
		}
		public int ConvertFilePathToFileId(string FilePath, int PortalID)
		{
			string FileName = "";
			string FolderName = "";
			int FileId = -1;
			if (!String.IsNullOrEmpty(FilePath)) {
				FileName = FilePath.Substring(FilePath.LastIndexOf("/") + 1);
				FolderName = FilePath.Replace(FileName, "");
			}
			FileController objFiles = new FileController();
			FolderController objFolders = new FolderController();
			FolderInfo objFolder = objFolders.GetFolder(PortalID, FolderName, false);
			if (objFolder != null) {
				FileInfo objFile = objFiles.GetFile(FileName, PortalID, objFolder.FolderID);
				if (objFile != null) {
					FileId = objFile.FileId;
				}
			}
			return FileId;
		}
		public void DeleteFile(int PortalId, string FileName, int FolderID, bool ClearCache)
		{
			DataProvider.Instance().DeleteFile(PortalId, FileName, FolderID);
			if (ClearCache) {
				GetAllFilesRemoveCache();
			}
		}
		public void DeleteFiles(int PortalId)
		{
			DeleteFiles(PortalId, true);
		}
		public void DeleteFiles(int PortalId, bool ClearCache)
		{
			DataProvider.Instance().DeleteFiles(PortalId);
			if (ClearCache) {
				GetAllFilesRemoveCache();
			}
		}
		public DataTable GetAllFiles()
		{
			DataTable dt = (DataTable)DataCache.GetCache("GetAllFiles");
			if (dt == null) {
				dt = DataProvider.Instance().GetAllFiles();
				DataCache.SetCache("GetAllFiles", dt);
			}
			if (dt != null) {
				return dt.Copy();
			} else {
				return new DataTable();
			}
		}
		public void GetAllFilesRemoveCache()
		{
			DataCache.RemoveCache("GetAllFiles");
		}
		public FileInfo GetFile(string FileName, int PortalId, int FolderID)
		{
			return (FileInfo)CBO.FillObject(DataProvider.Instance().GetFile(FileName, PortalId, FolderID), typeof(FileInfo));
		}
		public FileInfo GetFileById(int FileId, int PortalId)
		{
			FileInfo objFile;
			string strCacheKey = "GetFileById" + FileId.ToString();
			objFile = (FileInfo)DataCache.GetCache(strCacheKey);
			if (objFile == null) {
				objFile = (FileInfo)CBO.FillObject(DataProvider.Instance().GetFileById(FileId, PortalId), typeof(FileInfo));
				if (objFile != null) {
					int intCacheTimeout = 20 * Convert.ToInt32(Host.PerformanceSetting);
					DataCache.SetCache(strCacheKey, objFile, TimeSpan.FromMinutes(intCacheTimeout));
				}
			}
			return objFile;
		}

        public FileInfo GetFileByUniqueID(Guid UniqueId)
        {
            FileInfo objFile = default(FileInfo);
            objFile = (FileInfo)CBO.FillObject(DataProvider.Instance().GetFileByUniqueID(UniqueId), typeof(FileInfo));
            return objFile;
        }


		public byte[] GetFileContent(int FileId, int PortalId)
		{
			byte[] objContent = null;
			IDataReader dr = null;
			try {
				dr = DataProvider.Instance().GetFileContent(FileId, PortalId);
				if (dr.Read()) {
					objContent = System.Text.Encoding.Default.GetBytes((dr["Content"]).ToString());
				}
			} catch (Exception ex) {
				DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
			} finally {
				CBO.CloseDataReader(dr, true);
			}
			return objContent;
		}
		public IDataReader GetFiles(int PortalId, int FolderID)
		{
			return DataProvider.Instance().GetFiles(PortalId, FolderID);
		}

		public void UpdateFileContent(int FileId, Stream Content)
		{
            if (Content != null)
            {
                BinaryReader objBinaryReader = new BinaryReader(Content);
                byte[] objContent = objBinaryReader.ReadBytes(Convert.ToInt32(Content.Length));
                objBinaryReader.Close();
                Content.Close();
                DataProvider.Instance().UpdateFileContent(FileId, objContent);
            }
            else
            {
                DataProvider.Instance().UpdateFileContent(FileId, null);
            }
		    UpdateFileVersion(FileId);
		}
		public void UpdateFileContent(int FileId, byte[] Content)
		{
			DataProvider.Instance().UpdateFileContent(FileId, Content);
		    UpdateFileVersion(FileId);
		}

        public static XmlNode SerializeFile(XmlDocument xmlFile, FileInfo objFile)
        {
            XmlNode nodeTab = default(XmlNode);

            CBO.SerializeObject(objFile, xmlFile);

            nodeTab = xmlFile.SelectSingleNode("file");
            nodeTab.Attributes.Remove(nodeTab.Attributes["xmlns:xsd"]);
            nodeTab.Attributes.Remove(nodeTab.Attributes["xmlns:xsi"]);

            return nodeTab;
        }

        public static FileInfo DeserializeFile(XmlNode nodeFile, int portalId, int folderId)
        {
            FileController fileCtrl = new FileController();
            FileInfo objFile = new FileInfo();

            XmlNode node = nodeFile.SelectSingleNode("file");

            objFile.UniqueId = new Guid(XmlUtils.GetNodeValue(node.CreateNavigator(), "uniqueid"));
            objFile.VersionGuid = new Guid(XmlUtils.GetNodeValue(node.CreateNavigator(), "versionguid"));
            objFile.PortalId = portalId;
            objFile.FileName = XmlUtils.GetNodeValue(node.CreateNavigator(), "filename");
            objFile.Folder = XmlUtils.GetNodeValue(node.CreateNavigator(), "folder");
            objFile.FolderId = folderId;
            objFile.ContentType = XmlUtils.GetNodeValue(node.CreateNavigator(), "contenttype");
            objFile.Extension = XmlUtils.GetNodeValue(node.CreateNavigator(), "extension");
            objFile.StorageLocation = XmlUtils.GetNodeValueInt(node, "storagelocation");
            objFile.IsCached = XmlUtils.GetNodeValueBoolean(node, "iscached", false);
            objFile.Size = XmlUtils.GetNodeValueInt(node, "size", Null.NullInteger);
            objFile.Width = XmlUtils.GetNodeValueInt(node, "width", Null.NullInteger);
            objFile.Height = XmlUtils.GetNodeValueInt(node, "height", Null.NullInteger);

            // create/update file
            FileInfo objFileOriginal = fileCtrl.GetFileByUniqueID(objFile.UniqueId);
            if (objFileOriginal == null)
            {
                objFile.FileId = fileCtrl.AddFile(objFile);
            }
            else
            {
                objFile.FileId = objFileOriginal.FileId;
                fileCtrl.UpdateFile(objFile);
                objFile.FileId = fileCtrl.GetFileByUniqueID(objFile.UniqueId).FileId;
            }

            return objFile;
        }

        #region "Obsolete Methods"

        [Obsolete("This function has been replaced by AddFile(ByVal file As FileInfo)")]
        public int AddFile(FileInfo file, string FolderPath)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(file.PortalId, FolderPath, false);
            file.FolderId = objFolder.FolderID;
            file.Folder = FolderPath;
            return AddFile(file);
        }

        [Obsolete("This function has been replaced by AddFile(ByVal file As FileInfo)")]
        public int AddFile(int PortalId, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string FolderPath)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            FileInfo objFile = new FileInfo();

            objFile.UniqueId = Guid.NewGuid();
            objFile.VersionGuid = Guid.NewGuid();

            objFile.PortalId = PortalId;
            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = FileSystemUtils.FormatFolderPath(FolderPath);
            objFile.FolderId = objFolder.FolderID;
            objFile.IsCached = true;

            return AddFile(objFile);
        }

        [Obsolete("This function has been replaced by AddFile(ByVal file As FileInfo)")]
        public int AddFile(int PortalId, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string FolderPath, bool ClearCache)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            FileInfo objFile = new FileInfo();

            objFile.UniqueId = Guid.NewGuid();
            objFile.VersionGuid = Guid.NewGuid();

            objFile.PortalId = PortalId;
            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = FileSystemUtils.FormatFolderPath(FolderPath);
            objFile.FolderId = objFolder.FolderID;
            objFile.IsCached = ClearCache;

            return AddFile(objFile);
        }

        [Obsolete("This function has been replaced by DeleteFile(PortalId, FileName, FolderID, ClearCache)")]
        public void DeleteFile(int PortalId, string FileName, string FolderPath, bool ClearCache)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            DeleteFile(PortalId, FileName, objFolder.FolderID, ClearCache);
        }

        [Obsolete("This function has been replaced by DeleteFile(PortalId, FileName, FolderID, ClearCache)")]
        public void DeleteFile(int PortalId, string FileName, string FolderPath)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            DeleteFile(PortalId, FileName, objFolder.FolderID, true);
        }

        [Obsolete("This function has been replaced by GetFile(FileName, PortalId, FolderID)")]
        public FileInfo GetFile(string FilePath, int PortalId)
        {
            FolderController objFolders = new FolderController();
            string FileName = Path.GetFileName(FilePath);
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FilePath.Replace(FileName, ""), false);
            if (objFolder == null)
            {
                return null;
            }
            else
            {
                return GetFile(FileName, PortalId, objFolder.FolderID);
            }
        }

        [Obsolete("This function has been replaced by GetFile(FileName, PortalId, FolderID)")]
        public FileInfo GetFile(string FileName, int PortalId, string FolderPath)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            if (objFolder == null)
            {
                return null;
            }
            else
            {
                return GetFile(FileName, PortalId, objFolder.FolderID);
            }
        }

        [Obsolete("This function has been replaced by GetFiles(PortalId, FolderID)")]
        public IDataReader GetFiles(int PortalId, string FolderPath)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            if (objFolder == null)
            {
                return null;
            }
            return GetFiles(PortalId, objFolder.FolderID);
        }

        [Obsolete("This function has been replaced by ???")]
        public ArrayList GetFilesByFolder(int PortalId, string FolderPath)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false);
            if (objFolder == null)
            {
                return null;
            }
            return CBO.FillCollection(GetFiles(PortalId, objFolder.FolderID), typeof(FileInfo));
        }

        [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")]
        public void UpdateFile(int PortalId, string OriginalFileName, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string SourceFolder, string DestinationFolder)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, DestinationFolder, false);
            FileInfo objFile = GetFile(OriginalFileName, PortalId, objFolder.FolderID);

            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = DestinationFolder;

            if ((objFile != null))
            {
                UpdateFile(objFile);
            }
        }

        [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")]
        public void UpdateFile(int PortalId, string OriginalFileName, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string SourceFolder, string DestinationFolder,
        bool ClearCache)
        {
            FolderController objFolders = new FolderController();
            FolderInfo objFolder = objFolders.GetFolder(PortalId, DestinationFolder, false);
            FileInfo objFile = GetFile(OriginalFileName, PortalId, objFolder.FolderID);

            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = DestinationFolder;

            if ((objFile != null))
            {
                UpdateFile(objFile);
            }
        }

        [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")]
        public void UpdateFile(int PortalId, string OriginalFileName, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string SourceFolder, string DestinationFolder,
        int FolderID, bool ClearCache)
        {
            FileInfo objFile = GetFile(OriginalFileName, PortalId, FolderID);

            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = DestinationFolder;
            objFile.FolderId = FolderID;

            if ((objFile != null))
            {
                UpdateFile(objFile);
            }
        }

        [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by AddFile(ByVal file As FileInfo)")]
        public int AddFile(int PortalId, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string FolderPath, int FolderID, bool ClearCache)
        {
            FileInfo objFile = new FileInfo();

            objFile.UniqueId = Guid.NewGuid();
            objFile.VersionGuid = Guid.NewGuid();

            objFile.PortalId = PortalId;
            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = FileSystemUtils.FormatFolderPath(FolderPath);
            objFile.FolderId = FolderID;

            if (ClearCache)
            {
                GetAllFilesRemoveCache();
            }

            return AddFile(objFile);
        }

        [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")]
        public void UpdateFile(int FileId, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string DestinationFolder, int FolderID)
        {
            FileInfo objFile = new FileInfo();

            objFile.FileId = FileId;
            objFile.VersionGuid = Guid.NewGuid();

            objFile.FileName = FileName;
            objFile.Extension = Extension;
            objFile.Size = Convert.ToInt32(Size);
            objFile.Width = Width;
            objFile.Height = Height;
            objFile.ContentType = ContentType;
            objFile.Folder = FileSystemUtils.FormatFolderPath(DestinationFolder);
            objFile.FolderId = FolderID;

            UpdateFile(objFile);
        }

        #endregion


	}
}
